﻿using System.IO;
using System.Text;
using XcoAppSpaces.Contracts.Transport;
using XcoAppSpaces.Transport.Sockets;
using NUnit.Framework;
using System;

namespace test.XcoAppSpaces.Transport.Sockets
{
	[TestFixture]
	public class TransferHelperTests
	{
		[Test]
		public void MsgToByte()
		{
			string remoteAddr = "xco://test";
			string contenInfo = "test";
			byte[] addr = Encoding.UTF8.GetBytes(remoteAddr);
			byte[] contenInfoLen = Encoding.UTF8.GetBytes(contenInfo);
			byte[] context = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
			byte[] content = new byte[] { 5, 6, 7, 8, 9, 0, 255 };

			XcoMessage tmp = new XcoMessage
								{
									//RemoteAddress = remoteAddr,
									ContentInfo = contenInfo,
									Content = content,
									CausalityContext = context
								};
			TransferHelper transferHelper = new TransferHelper();
			byte[] result = transferHelper.Convert(tmp, remoteAddr);

			Assert.AreEqual(result.Length, addr.Length + contenInfoLen.Length + context.Length + content.Length + 5 * 4);
			//int len = 4 bytes
		}

		[Test]
		public void MsgToByte_Address_Null()
		{
			byte[] context = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
			byte[] content = new byte[] { 5, 6, 7, 8, 9, 0, 255 };

			XcoMessage tmp = new XcoMessage
			{
				//RemoteAddress = null,
				Content = content,
				CausalityContext = context
			};
			TransferHelper transferHelper = new TransferHelper();
			byte[] result = transferHelper.Convert(tmp, null);

			Assert.IsNull(result); //if address is null then result is also null
			//Assert.AreEqual(result.Length, 0 + context.Length + content.Length + 5 * 4);
		}

		[Test]
		public void MsgToByte_Content_Null()
		{
			string remoteAddr = "xco://test";
			byte[] addr = Encoding.UTF8.GetBytes(remoteAddr);
			byte[] context = new byte[] { 1, 2, 3, 4, 5, 6, 7 };

			XcoMessage tmp = new XcoMessage
			{
				//RemoteAddress = remoteAddr,
				Content = null,
				CausalityContext = context
			};
			TransferHelper transferHelper = new TransferHelper();
			byte[] result = transferHelper.Convert(tmp, remoteAddr);

			Assert.IsNull(result); //without content result is null (message with no content is invalid)
			//Assert.AreEqual(result.Length, addr.Length + context.Length + 5 * 4);
		}

		[Test]
		public void MsgToByte_ContentInfo_Null()
		{
			string remoteAddr = "xco://test";
			byte[] addr = Encoding.UTF8.GetBytes(remoteAddr);
			byte[] context = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
			byte[] content = new byte[] { 5, 6, 7, 8, 9, 0, 255 };

			XcoMessage tmp = new XcoMessage
								 {
									 //RemoteAddress = remoteAddr,
									 Content = content,
									 ContentInfo = null,
									 CausalityContext = context
								 };
			TransferHelper transferHelper = new TransferHelper();
			byte[] result = transferHelper.Convert(tmp, remoteAddr);

			Assert.AreEqual(result.Length, addr.Length + content.Length + context.Length + 5 * 4); //int len = 4 bytes
		}

		[Test]
		public void MsgToByteContextNull()
		{
			string remoteAddr = "xco://test";
			byte[] addr = Encoding.UTF8.GetBytes(remoteAddr);

			byte[] content = new byte[] { 5, 6, 7, 8, 9, 0, 255 };

			XcoMessage tmp = new XcoMessage
			{
				//RemoteAddress = remoteAddr,
				Content = content,
				CausalityContext = null
			};
			TransferHelper transferHelper = new TransferHelper();
			byte[] result = transferHelper.Convert(tmp, remoteAddr);

			Assert.AreEqual(result.Length, addr.Length + content.Length + 5 * 4); //int len = 4 bytes
		}

		[Test]
		public void ByteToMsg()
		{
			string remoteAddr = "xco://test";
			string contenInfo = "test_information";
			byte[] addr = Encoding.UTF8.GetBytes(remoteAddr);
			byte[] contInfo = Encoding.UTF8.GetBytes(contenInfo);
			byte[] context = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
			byte[] content = new byte[] { 5, 6, 7, 8, 9, 0, 255 };

			MemoryStream mem = new MemoryStream();
			BinaryWriter writer = new BinaryWriter(mem);
			writer.Write(BitConverter.GetBytes(addr.Length + contInfo.Length + content.Length + context.Length + 4 * 4));
			writer.Write(BitConverter.GetBytes(addr.Length));
			writer.Write(BitConverter.GetBytes(contInfo.Length));
			writer.Write(BitConverter.GetBytes(context.Length));
			writer.Write(BitConverter.GetBytes(content.Length));
			writer.Write(addr);
			writer.Write(contInfo);
			writer.Write(context);
			writer.Write(content);
			writer.Flush();
			mem.Position = 0;

			BinaryReader binReader = new BinaryReader(mem);

			TransferHelper transferHelper = new TransferHelper();
			string remoteAddrResult;
			XcoMessage tmp = transferHelper.Convert(binReader, out remoteAddrResult, () => { }, _ => { });

			Assert.AreEqual(remoteAddrResult, remoteAddr);
			Assert.AreEqual(tmp.ContentInfo, contenInfo);
			Assert.AreEqual(tmp.CausalityContext, context);
			Assert.AreEqual(tmp.Content, content);
		}
	}
}
